這裡一併解說第二層及第三層,第二層利用MAC地址去找尋封包的目的地位置,而第三層IP層主要為路由功能,利用IP地址將封包送達不同網段的IP,路由器和交換機會紀錄IP地址和MAC地址的映射關係。
昨天我們能透過packet, _ = s.recvfrom(65565)取得整段最原始的封包,這時我們來解析他,第二層的header長度固定為14,第三層的header固定為20,如下所示
Eth_header = packet[:14]
Ip_header = packet[14:34]
Eth_header比較好解釋,packet[:6]
和packet[6:12]
分別代表來源Mac Address和目的地Mac Address,但是還是需要decode一下,可以根據github上的ethAddrDecode進行decode再print出人看得懂的MAC address,後面兩位表示要走乙太網什麼協議,具體的協議可以根據https://zh.wikipedia.org/wiki/%E4%BB%A5%E5%A4%AA%E7%B1%BB%E5%9E%8B
例如最典型的0x0800就是IPv4
ip_header雖然長度只有20,也就是20bytes,但是裡面卻蘊含了許多訊息,如下圖所示,8bits = 1byte,所以一行有4個byte
python提供struct,用來解構和打包二進位的bytes數據,我們用他來解構ip_header的數據
struct.unpack('!BBHHHBBH4s4s' , ip_header)
第一個參數的英文數字的format如下
FORMAT [C TYPE] [PYTHON TYPE] [BYTES] [NOTES]
x pad byte no value
c char string of length 1 1
b signed char integer 1 (3)
B unsigned char integer 1 (3)
? _Bool bool 1 (1)
h short integer 2 (3)
H unsigned short integer 2 (3)
i int integer 4 (3)
I unsigned int integer 4 (3)
l long integer 4 (3)
L unsigned long integer 4 (3)
q long long integer 8 (2), (3)
Q unsigned long long integer 8 (2), (3)
f float float 4 (4)
d double float 8 (4)
s char[] string
p char[] string
P void * integer (5), (3)
符號的意思如下
CHARACTER [BYTE ORDER] [SIZE] [ALIGNMENT]
@ native native native
= native standard none
< little-endian standard none
> big-endian standard none
! network(=big-endian) standard none
所以這個unpack出來後會分別得到IHL_VERSION, TYPE_OF_SERVICE, TOTAL_LEN, PKTID, FRAGMENT_STATUS, TIME_TO_LIVE, PROTOCOL, Checksum, SRC_IP,DEST_IP,快速說一下header裡這些東西的作用
IHL_VERSION:同時包含版本訊息和ip header長度的訊息
TYPE_OF_SERVICE:服務類型,八個bits,一般為八個0,每個bit組合有不同的意思
系列的成果將會放在這:https://github.com/kaichiachen/pytcpdump
文章配合著程式碼有助於學習 :)